package laba8;

import interfaces.task8.CyclicCollection;
import interfaces.task8.CyclicItem;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Implementation of the CyclicCollection
 * @author yakimovich
 */
public class CyclicCollectionImpl
        implements CyclicCollection, Serializable {

    private List<CyclicItem> cyclicCol = new ArrayList<>();

    /**
     * The method adds an element to the CyclicCollection
     * @param ci item for adding
     * @eturns true if the element is added, otherwise false
     */
    @Override
    public boolean add(CyclicItem ci) {
        int size = cyclicCol.size();

        if (ci == null) {
            throw new NullPointerException();
        }

        if (cyclicCol.contains(ci)) {
            throw new IllegalArgumentException();
        }

        if (size == 0) {
            ci.setNextItem(ci);
        } else {
            if (size > 0) {
                cyclicCol.get(size - 1).setNextItem(ci);
                ci.setNextItem(cyclicCol.get(0));
            } else {
            }
        }
        return cyclicCol.add(ci);
    }

    /**
     * The method inserts the element after the specified element.
     * @param ci element from CyclicCollection
     * @param ci1 the added element
     */
    @Override
    public void insertAfter(CyclicItem ci, CyclicItem ci1) {
        if (ci == null || ci1 == null) {
            throw new NullPointerException();
        }

        if (!cyclicCol.contains(ci) || cyclicCol.contains(ci1)) {
            throw new IllegalArgumentException();
        }

        int index = cyclicCol.indexOf(ci);

        ci1.setNextItem(ci.nextItem());
        ci.setNextItem(ci1);
        cyclicCol.add(index + 1, ci1);
    }

    /**
     * The method returns the first element of the CyclicCollection
     * @return the first element of the CyclicCollection
     */
    @Override
    public CyclicItem getFirst() {
        if (size() == 0) {
            return null;
        }
        return cyclicCol.get(0);
    }

    /**
     * The Method removes the specified element. 
     * @param ci element for removing 
     * @return true if the element is removed, otherwise false
     */
    @Override
    public boolean remove(CyclicItem ci) {
        boolean result = false;
        if (ci == null) {
            throw new NullPointerException();
        }
        if (cyclicCol.remove(ci)) {
            result = true;
        }

        return result;
    }

    /**
     * @return size of the CyclicCollection
     */
    @Override
    public int size() {
        return cyclicCol.size();
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final CyclicCollectionImpl other 
                = (CyclicCollectionImpl) obj;
        if (!Objects.equals(this.cyclicCol, other.cyclicCol)) {
            return false;
        }
        return true;
    }
}
